// import globalInterface from '@/common/global'
import { VuexModule, Module, Action, Mutation, getModule, config } from 'vuex-module-decorators'
import cookie, { TOKEN_KEY } from '@/libs/util.cookies'
import { AccountLogin, GetUserInfo } from '@/api/sys.login'
import store from '@/store'
import { Message, MessageBox } from 'element-ui'
import { dbSet, dbGet, dbStoreName } from '@/libs/util.db'
import router from '@/router'

config.rawError = true // 正常显示action的异常以便排查错误

export interface IUserState {
  token: string;
  name: string;
  avatar: string;
  roles: string[]
}
// 常量用于赋值使用
const TOKEN = 'token'
const NAME = 'name'
const AVATAR = 'avatar'
const ROLES = 'roles'
// @Module 标记当前为module
// module本身有几种可以配置的属性
// 1、namespaced:boolean 启/停用 分模块
// 2、stateFactory:boolean 状态工厂
// 3、dynamic:boolean 在store创建之后，再添加到store中。 开启dynamic之后必须提供下面的属性
// 4、name:string 指定模块名称
// 5、store:Vuex.Store实体 提供初始的store
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState {
  // 在需要引用的地方单独引用该store文件即可注入。
  // 好处：灵活使用，仅仅在需要引入的地方才注入到store中去
  // 缺点：需要单独引入文件
  public token = cookie.get(TOKEN_KEY) || ''
  public name = dbGet({ dbName: dbStoreName.user, path: 'userName' })
  public avatar = ''
  public roles: string[] = []

  @Mutation
  private SET_USER_INFO<T> (payload: { key: string, val: T }) {
    const { key, val } = payload
    if (Object.prototype.hasOwnProperty.call(this, key)) {
      (this as any)[key] = val
    }
  }

  get accountName (): string {
    return this.name
  }

  // @Action({ rawError: true })
  @Action
  public Login (userInfo: { username: string; password: string }) {
    // 请求登录接口，拿到token
    let { username, password } = userInfo
    username = username.trim()
    return new Promise((resolve, reject) => {
      AccountLogin({ username, password }).then(async res => {
        if (res.data.code === 'success') {
          const token: string = res.data.data.token
          const name: string = res.data.data.name
          cookie.set(TOKEN_KEY, token)
          this.SET_USER_INFO({ key: TOKEN, val: token })
          this.SET_USER_INFO({ key: NAME, val: name })
          dbSet({ dbName: dbStoreName.user, path: 'userName', value: name })
          this.context.dispatch('loginSuccess')
          resolve(res.data)
        }
      }).catch(err => {
        Message({
          message: (err.data && err.data.message),
          type: 'error'
        })
        reject(err)
      })
    })
  }

  @Action
  public async GetUserInfo () {
    // 获取用户信息
    if (this.token === '') {
      throw Error('token无效！')
    }
    const { data } = await GetUserInfo({ token: this.token })
    if (!data) {
      throw Error('Verification failed, please Login again.')
    }
    const { roles, avatar } = data.data
    this.SET_USER_INFO({ key: AVATAR, val: avatar })
    this.SET_USER_INFO({ key: ROLES, val: roles })
  }

  @Action
  public Logout () {
    // 注销
    MessageBox.confirm('退出当前账户吗？', '确认操作', {
      type: 'warning'
    }).then(() => {
      // TODO await logout() 请求退出接口
      this.LogoutSubmit()
    }).catch(() => {
      Message({
        message: '放弃退出登录'
      })
    })
  }

  @Action
  public LogoutSubmit () {
    this.SET_USER_INFO({ key: AVATAR, val: '' })
    this.SET_USER_INFO({ key: ROLES, val: [] })
    this.SET_USER_INFO({ key: TOKEN, val: '' })
    this.SET_USER_INFO({ key: NAME, val: '' })
    dbSet({ dbName: dbStoreName.user, path: 'userName', value: '' })
    cookie.remove(TOKEN_KEY)
    router.push({
      path: '/login'
    })
  }

  @Action
  public loginSuccess () {
    this.context.dispatch('InitSetting') // 初始化设置变量
  }
}
// getModule得到一个类型安全的store,module必须提供name属性
export const UserModule = getModule(User)
